<template>
  <a-modal
    :title="title"
    :width="640"
    :visible="visible"
    :confirmLoading="confirmLoading"
    :maskClosable="false"
    :keyboard="false"
    @ok="handleSubmit"
    @cancel="handleCancel"
  >
    <a-form :form="form">
      <a-form-item label="班次名称" :labelCol="labelCol" :wrapperCol="wrapperCol" v-bind="validator.nameValidProps">
        <s-input
          :maxLength="32"
          :limit="32"
          v-decorator="[
            'name',
            {
              initialValue: record.name,
              rules: [
                { required: true, whitespace: true, message: '班次名称不能为空' },
                { validator: validator.nameValidator }
              ]
            }
          ]"
        />
      </a-form-item>
      <a-form-item label="班次时间" :labelCol="labelCol" :wrapperCol="wrapperCol">
        <a-input
          style="display: none"
          v-decorator="[
            'shiftTimeField',
            {
              initialValue: 'default',
              rules: [
                { required: true, whitespace: true, message: '班次时间不能为空' },
                { validator: handleShiftTimeValidate },
                { validator: validator.shiftTimeFieldValidator }
              ]
            }
          ]"
        />
        <a-row type="flex" justify="space-between" align="middle">
          <a-form-item style="width: 45%;margin-bottom: 0;">
            <a-time-picker
              :allowClear="false"
              format="HH:mm"
              style="width: 100%"
              :value="record.startTime"
              @change="time => handleShiftTimeChange('startTime', time)"
            /> </a-form-item
          >-
          <a-form-item style="width: 45%;margin-bottom: 0;">
            <a-time-picker
              :allowClear="false"
              format="HH:mm"
              style="width: 100%"
              :value="record.endTime"
              @change="time => handleShiftTimeChange('endTime', time)"
            />
          </a-form-item>
        </a-row>
      </a-form-item>
      <a-form-item label="停机时间" :labelCol="labelCol" :wrapperCol="wrapperCol">
        <a-input
          style="display: none"
          v-decorator="[
            'planTimeListField',
            {
              initialValue: 'default',
              rules: [{ validator: handleplanTimeListValidate }]
            }
          ]"
        />
        <a @click="handleAddplanTimeList">添加</a>
        <a-row
          v-for="(time, index) in record.planTimeList"
          :key="index"
          type="flex"
          justify="space-between"
          align="middle"
          :class="{ hidden: time.deleted === 1 }"
        >
          <a-select style="width: 25%" v-model="time.planId">
            <a-select-option v-for="type in planTypes" :key="type.id" :value="type.id">{{ type.name }}</a-select-option>
          </a-select>
          <a-time-picker
            :allowClear="false"
            format="HH:mm"
            style="width: 30%"
            :value="time.startTime"
            @change="time => handlePlanTimeListChange('startTime', index, time)"
          />-
          <a-time-picker
            :allowClear="false"
            format="HH:mm"
            style="width: 30%"
            :value="time.endTime"
            @change="time => handlePlanTimeListChange('endTime', index, time)"
          />
          <a-icon class="delete-icon" style="cursor: pointer;" type="close" @click="handleDelPlanTimeList(index)" />
        </a-row>
      </a-form-item>
    </a-form>
  </a-modal>
</template>

<script>
import moment from 'moment';
import { createShift, updateShift, validateShiftField } from '@/api/shift';
import { isTimeContain, isTimeCross } from '@/utils/util';
import { asyncValidateMixin } from '@/utils/mixin';
import { SInput } from '@/components';

export default {
  name: 'ShiftFrom',
  mixins: [asyncValidateMixin],
  props: {
    shifts: {
      type: Array,
      default: () => []
    }
  },
  components: {
    SInput
  },
  data() {
    return {
      labelCol: {
        xs: { span: 24 },
        sm: { span: 5 }
      },
      wrapperCol: {
        xs: { span: 24 },
        sm: { span: 15 }
      },
      visible: false,
      confirmLoading: false,
      form: null,
      title: '',
      record: {
        id: 0,
        name: '',
        startTime: undefined,
        endTime: undefined,
        planTimeList: []
      }
    };
  },
  computed: {
    planTypes() {
      // return this.$store.getters.planTypes;
      return [{ id: 1, name: '休息' }];
    }
  },
  created() {
    this.form = this.$form.createForm(this, { name: 'ShiftForm' });
    this.$_asyncValidateMixin_init([
      {
        fieldName: 'name',
        caller: validateShiftField,
        extraParams: () => {
          return {
            id: this.record.id,
            userId: this.$store.state.user.info.id
          };
        }
      },
      {
        fieldName: 'shiftTimeField',
        caller: validateShiftField,
        extraParams: () => {
          const { startTime, endTime } = this.record;
          const from = startTime ? moment(this.record.startTime).format('HH:mm') : '';
          const to = endTime ? moment(this.record.endTime).format('HH:mm') : '';
          return {
            value: `${from}-${to}`,
            id: this.record.id,
            userId: this.$store.state.user.info.id
          };
        }
      }
    ]);
  },
  methods: {
    init() {
      this.record = {
        id: 0,
        name: '',
        startTime: undefined,
        endTime: undefined,
        planTimeList: []
      };
    },

    add() {
      this.visible = true;
      this.type = 'ADD';
      this.title = '新建班次';
      this.init();
    },

    edit(record) {
      this.visible = true;
      this.type = 'EDIT';
      this.title = '编辑班次';
      const { id, name, startTime, endTime, planTimeList } = record;
      const oplanTimeList = planTimeList.map(item => {
        const oItem = Object.assign({}, item);
        oItem.startTime = moment(oItem.startTime, 'HH:mm');
        oItem.endTime = moment(oItem.endTime, 'HH:mm');
        oItem.deleted = 0;
        oItem.planId = 1;
        return oItem;
      });
      this.record = {
        id: id,
        name: name,
        startTime: startTime ? moment(startTime, 'HH:mm') : undefined,
        endTime: endTime ? moment(endTime, 'HH:mm') : undefined,
        planTimeList: oplanTimeList
      };
    },

    handleShiftTimeValidate(rule, value, callback) {
      const { startTime, endTime } = this.record;
      if (!startTime || !endTime) {
        callback(new Error('班次时间不能为空'));
      }
      callback();
    },

    handleplanTimeListValidate(rule, value, callback) {
      const { startTime, endTime } = this.record;
      const planTimeList = this.record.planTimeList.filter(item => item.deleted !== 1);
      // 没有停机时间 or 班次时间不完整
      if (planTimeList.length === 0 || !startTime || !endTime) {
        callback();
      }

      const rangeFrom = moment(startTime).format('HH:mm');
      const rangeTo = moment(endTime).format('HH:mm');
      const range = {
        from: rangeFrom,
        to: rangeTo
      };

      for (let index = 0; index < planTimeList.length; index++) {
        // 停机时间不完整
        if (!planTimeList[index].startTime || !planTimeList[index].endTime) {
          callback(new Error(`停机时间不能为空`));
          break;
        }

        const periodFrom = moment(planTimeList[index].startTime).format('HH:mm');
        const periodTo = moment(planTimeList[index].endTime).format('HH:mm');
        const period = {
          from: periodFrom,
          to: periodTo
        };
        // 当前停机时间是否在班次时间内
        if (!isTimeContain(range, period)) {
          callback(new Error('停机时间不能在班次之外，且不能与班次内其他的停机时间重叠'));
          break;
        }
        // 当前停机时间是否跟其他停机时间交叉（只对比前面的数据）
        let isError = false;
        for (let j = 0; j < index; j++) {
          const jRangeFrom = moment(planTimeList[j].startTime).format('HH:mm');
          const jRangeTo = moment(planTimeList[j].endTime).format('HH:mm');
          const jRange = {
            from: jRangeFrom,
            to: jRangeTo
          };
          if (isTimeCross(jRange, period)) {
            isError = true;
            callback(new Error('停机时间不能在班次之外，且不能与班次内其他的停机时间重叠'));
            break;
          }
        }
        if (isError) {
          break;
        }
      }
      callback();
    },

    handleShiftTimeChange(prop, time) {
      this.record[prop] = time;
      const { startTime, endTime } = this.record;
      if (!startTime || !endTime) {
        return;
      }
      this.form.validateFields(['shiftTimeField'], { force: true }, () => {});
      this.form.validateFields(['planTimeListField'], { force: true }, () => {});
    },

    handlePlanTimeListChange(prop, index, time) {
      this.record.planTimeList[index][prop] = time;
      const { startTime, endTime } = this.record.planTimeList[index];
      if (!startTime || !endTime) {
        return;
      }
      this.form.validateFields(['planTimeListField'], { force: true }, () => {});
    },

    handleAddplanTimeList() {
      if (this.planTypes.length === 0) {
        this.$notification.warning({
          message: '操作失败',
          description: '请先设置计划停机类型'
        });
        return;
      }
      // 这里需要更新字段值，防止直接提交会跳过该值的校验
      this.form.setFieldsValue({
        planTimeListField: Math.random()
      });
      // 取计划停机类型第一条作为默认值
      const defaultId = this.planTypes[0].id;
      const defaultName = this.planTypes[0].name;
      this.record.planTimeList.push({
        planId: defaultId,
        startTime: undefined,
        endTime: undefined,
        deleted: 0,
        name: defaultName
      });
    },

    handleDelPlanTimeList(index) {
      this.record.planTimeList[index].deleted = 1;
      this.form.validateFields(['planTimeListField'], { force: true });
    },

    handleSubmit() {
      const {
        form: { validateFields, getFieldsValue }
      } = this;
      this.confirmLoading = true;
      const fieldNames = this.$_asyncValidateMixin_fieldsFilter(getFieldsValue());
      validateFields(fieldNames, (errors, values) => {
        if (!errors) {
          const { name } = this.form.getFieldsValue();
          const oplanTimeList = this.record.planTimeList
            .filter(item => {
              return item.id || (!item.id && item.deleted !== 1);
            })
            .map(item => {
              const oItem = Object.assign({}, item);
              oItem.startTime = oItem.startTime ? moment(oItem.startTime).format('HH:mm') : '';
              oItem.endTime = oItem.endTime ? moment(oItem.endTime).format('HH:mm') : '';
              return oItem;
            });
          const params = {
            id: this.record.id,
            name: name.trim(),
            startTime: moment(this.record.startTime).format('HH:mm'),
            endTime: moment(this.record.endTime).format('HH:mm'),
            planTimeList: oplanTimeList,
            userId: this.$store.state.user.info.id
          };
          let shiftApi = null;
          if (this.type === 'EDIT') {
            shiftApi = updateShift;
          } else {
            shiftApi = createShift;
          }
          shiftApi(params)
            .then(res => {
              this.$message.success(res.message);
              this.$emit('ok');
              this.handleCancel();
            })
            .catch(err => {})
            .finally(() => {
              this.confirmLoading = false;
            });
        } else {
          this.confirmLoading = false;
        }
      });
    },

    handleCancel() {
      this.visible = false;
      this.form.resetFields();
      this.$_asyncValidateMixin_resetFields();
      this.init();
    }
  }
};
</script>

<style lang="less" scoped>
.hidden {
  display: none;
}
</style>
